package com.howard.core;

import java.lang.reflect.Field;
import java.util.Properties;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.util.ReflectionUtils;

import com.howard.core.annotations.Property;

/**
 * 加载属性文件支持注解
 *
 * @author Howard.He
 *
 */
public class AnnotationBeanPostProcessor extends PropertyPlaceholderConfigurer
		implements BeanPostProcessor, InitializingBean {

	private static Logger logger = LoggerFactory
			.getLogger(AnnotationBeanPostProcessor.class);

	private Properties props;

	@SuppressWarnings("rawtypes")
	private Class[] enableClassList = { String.class };

	public void setEnableClassList(
			@SuppressWarnings("rawtypes") Class[] enableClassList) {
		this.enableClassList = enableClassList;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		props = mergeProperties();
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		if(logger.isInfoEnabled()) {
			logger.info("property annotation initalization");
		}
		Field[] fileds = bean.getClass().getDeclaredFields();
		for (Field field : fileds) {
			if (field.isAnnotationPresent(Property.class)) {
				if (filterType(field.getType().getName())) {
					Property p = field.getAnnotation(Property.class);
					ReflectionUtils.makeAccessible(field);
					try {
						field.set(bean, props.getProperty(p.name()));
					} catch (IllegalArgumentException e) {
						logger.error("property name illegal argument");
					} catch (IllegalAccessException e) {
						logger.error("property name illegal access");
					}
				}
			}
		}
		return bean;
	}

	private boolean filterType(String type) {
		if (StringUtils.isNotBlank(type)) {
			for (@SuppressWarnings("rawtypes")
			Class c : enableClassList) {
				if (c.getName().equals(type)) {
					return true;
				}
			}
			return false;
		}
		return false;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		return bean;
	}

}
